/*
* Copyright 2018 Shanxi Lu'an Taihang Laihui Net Tech co.,LTD.
*/
package com.laihuichuxing.pool.impl;

import com.google.common.collect.Maps;
import com.laihuichuxing.mongo.client.GeoSpatialMongoClient;
import com.laihuichuxing.mongo.model.GeoDto;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.StampedLock;

/**
 * Description:
 *
 * @author: Qinxuefeng
 * @since: 1.0
 * Create Date Time: 2018/11/2 17:17
 * Update Date Time:
 */
abstract class BaseLbs4Mongo {

    private final StampedLock sl = new StampedLock();
    /**
     * Description: 资源提交到MongoDB
     *
     * @param lon      经度
     * @param lat      纬度
     * @param phone    电话号
     * @param cityCode 城市编码
     * @return 无
     * @author QinXueFeng
     * Create Date Time:
     * Update Date Time:
     */
    public void offer(String lon, String lat, String phone, String cityCode) {
        GeoSpatialMongoClient client = getClient(cityCode,phone);
        double longitude = Double.parseDouble(lon) / 1000000D;
        double latitude = Double.parseDouble(lat) / 1000000D;
        // 创建索引
        if (client.count() == 0) {
            client.geo2dsphereIndex();
        }
        client.upsertLonAndLatByMobile(phone, longitude, latitude);
        client=null;
    }

    /**
     * Description: 取出自己
     *
     * @param mobile   手机号
     * @param cityCode 城市编码
     * @return 手机号
     * @author QinXueFeng
     * Create Date Time:
     * Update Date Time:
     */
    public String takeMe(String mobile, String cityCode) throws Exception {
        GeoSpatialMongoClient client = getClient(cityCode, mobile);
        GeoDto byMobile = client.getByMobile(mobile);
        client=null;
        return byMobile == null ? "" : byMobile.getMobile();
    }

    abstract GeoSpatialMongoClient getClient(String cityCode, String phone);

    /**
     * Description: 删除
     *
     * @param mobile     手机号
     * @param collection 城市编码
     * @return 无
     * @author QinXueFeng
     * Create Date Time:
     * Update Date Time:
     */
    public void del(String mobile, String collection) {
        GeoSpatialMongoClient client = getClient(collection, mobile);
        client.deleteByKey("mobile", mobile);
        client=null;
    }

    /**
     * Description: 司机乘客反向取出资源
     *
     * @param lon         经度
     * @param lat         纬度
     * @param ListSize    返回条数
     * @param minDistance 最小距离
     * @param maxDistance 最大距离
     * @param cityCode    城市编码
     * @return
     * @author QinXueFeng
     * Create Date Time: 2018/11/5 11:51
     * Update Date Time:
     */
    List<Map<String, String>> take(String cityCode, String lon,
                                   String lat,String phone, int ListSize,
                                   double minDistance, double maxDistance) throws Exception {
        GeoSpatialMongoClient client = getClient(cityCode, phone);
        double longitude = Double.parseDouble(lon) / 1000000D;
        double latitude = Double.parseDouble(lat) / 1000000D;
        long stamp = sl.writeLock();
        List<Map<String, String>> lbsDtos = new ArrayList<>();
        List<GeoDto> list = client.near(longitude, latitude, maxDistance, minDistance, ListSize);
        findGeo(cityCode, phone, lbsDtos, list);
        sl.unlockWrite(stamp);
        if (lbsDtos.isEmpty()) {
            List<GeoDto> list2 = client.near(longitude, latitude, maxDistance, minDistance, ListSize+1);
            findGeo(cityCode, phone, lbsDtos, list2);
        }
        client=null;
        return lbsDtos;
    }

    private void findGeo(String cityCode, String phone, List<Map<String, String>> lbsDtos, List<GeoDto> list) {
        if(!list.isEmpty()) {
            for (GeoDto geoDto : list) {
                String mobile = geoDto.getMobile();
                if (!phone.equals(mobile)) {
                    del(mobile, cityCode);
                    Map<String, String> map = Maps.newHashMap();
                    map.put("mobile", mobile);
                    map.put("longitude", String.valueOf(geoDto.getLongitude()));
                    map.put("latitude", String.valueOf(geoDto.getLatitude()));
                    lbsDtos.add(map);
                }
            }
        }
    }

}
